package com.sls.game.common;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.sls.core.http.HttpClient;
import com.sls.core.socket.Head;
import com.sls.core.socket.ServerDisponseException;
import com.sls.core.util.DataConversion;
import com.sls.core.util.ProcessString;
import com.sls.core.util.ServerDateAndTime;
import com.sls.core.util.UtilMD5Encryption;
import com.sls.game.constant.ExceptionCodeDes;
import com.sls.game.dao.DownstreamUserDAO;
import com.sls.game.dao.GoodsInfoManageDAO;
import com.sls.game.dao.GoodsOrderDAO;
import com.sls.game.dao.GoodsOrderLogDAO;
import com.sls.game.dao.nutsnet.ChargeTypeInfoDAO;
import com.sls.game.parser.deductrefund.DeductionRefundResParse;
import com.sls.game.parser.sls.OrderStatusSendParse;
import com.sls.game.pojo.DeductionRefundInfo;
import com.sls.game.pojo.DownstreamUserInfo;
import com.sls.game.pojo.GoodsManageInfo;
import com.sls.game.pojo.GoodsOrderInfo;
import com.sls.game.pojo.SLSHttpInterfaceInfo;
import com.sls.game.pojo.nutsnet.ChargeTypeInfo;

/**
 * 
 * @description 支付退款
 * @author Wangxuegang
 * @date 2012-12-26
 */
public class DeductionRefund {

	private static Logger log = Logger.getLogger(DeductionRefund.class);

	/**
	 * 调用支付（扣款或退款）接口
	 * 
	 * @param info
	 * @param orderId
	 * @param paymentType
	 * @param orderTime
	 * @param paymentOrderNo
	 * @return
	 */
	public static DeductionRefundInfo invokeDeductRefund(
			SLSHttpInterfaceInfo info, String orderId, String paymentType,
			String orderTime, String paymentOrderNo, Head head,
			GoodsOrderDAO goodsOrderDAO) {
		DeductionRefundInfo deductionRefundInfo = new DeductionRefundInfo();
		// 用户编号
		deductionRefundInfo.setUserNo(info.getUserNo());
		// 手拉手订单号
		deductionRefundInfo.setOrderNo(orderId);
		String totalPrice = getOrderTotalPrice(goodsOrderDAO, orderId, head);
		// 支付费用
		deductionRefundInfo.setPaymentFee(totalPrice); // 单位:元
		// 支付类型
		deductionRefundInfo.setPaymentType(paymentType); // 支付类型(0 扣款,1 退款)
		// 下游用户IP地址
		deductionRefundInfo.setPaymentIP(info.getClientIp());
		deductionRefundInfo.setOrderTime(orderTime);
		deductionRefundInfo.setTradeNo(paymentOrderNo); // 支付单号
		DeductionRefundInfo deReFunInfo = null;

		deReFunInfo = sendDeductionOrRefundMsg(deductionRefundInfo, head);
		return deReFunInfo;
	}

	/**
	 * 查询订单总价
	 * 
	 * @param head
	 * @return
	 */
	private static String getOrderTotalPrice(GoodsOrderDAO goodsOrderDAO,
			String orderId, Head head) {
		GoodsOrderInfo order = goodsOrderDAO.queryByOrderId(orderId);
		int totalPrice = 0;
		if (order != null) {
			totalPrice = order.getTotalPrice();
			String total = DataConversion.converIntegerToString(String
					.valueOf(totalPrice));
			return total;
		} else {
			log.info("请求ID：" + head.getRequestId() + "查询订单总价异常");
			throw new ServerDisponseException("ORDER_TOTAL_PRICE_EXE",
					"查询订单总价异常");
		}
	}

	/**
	 * 从商品信息表中，查询该商品的售价
	 * 
	 * @param goodsId
	 * @return
	 */
	@SuppressWarnings("unused")
	private static String queryGoodsSalePrice(String goodsId, Head head,
			GoodsInfoManageDAO goodsInfoManageDAO) {
		String salePrice = "";
		GoodsManageInfo goodsManageInfo = null;
		try {
			goodsManageInfo = goodsInfoManageDAO
					.queryGoodsInfoByGoodsId(goodsId);
		} catch (Exception e) {
			log.error("Service处理[" + head.getRequestId() + "]的请求出现异常！");
			throw new ServerDisponseException(
					ExceptionCodeDes.ACCESS_DATABASE_ERROR.getCode(),
					ExceptionCodeDes.ACCESS_DATABASE_ERROR.getDescription());
		}

		if (goodsManageInfo != null) {
			salePrice = goodsManageInfo.getCommonSalePrice() + "";
		}

		return salePrice;
	}

	/**
	 * 按元充值时，(下游)交易总费用的计算
	 * 
	 * @param info
	 * @param chargeTypeName
	 * @param originalGoodsId
	 * @return
	 */
	public static String calculateTotalPrice(SLSHttpInterfaceInfo info,
			String chargeTypeName, String originalGoodsId,
			ChargeTypeInfoDAO chargeTypeInfoDAO) {
		String totalPrice = "";
		// 判断该字符串中是否含有"元"
		boolean flag1 = ProcessString.isContainYuan(chargeTypeName);
		if (flag1) {
			boolean flag2 = ProcessString.isHasDigital(chargeTypeName);
			if (flag2) {
				// 充值方式或计费类型Id
				ChargeTypeInfo chargeTypeInfo = new ChargeTypeInfo();
				chargeTypeInfo.setGoodsId(originalGoodsId);
				chargeTypeInfo.setChargetypeName(chargeTypeName);
				String buyNum = info.getBuyNum();
				String unitPrice = info.getUnitPrice();
				int buyNumVal = Integer.parseInt(buyNum);
				int unitPriceVal = DataConversion
						.converStringToInteger(unitPrice);
				int moneyVal = buyNumVal * unitPriceVal;
				String moneyStr = moneyVal + "";
				String money = DataConversion.converIntegerToString(moneyStr);
				totalPrice = money;
			} else {
				totalPrice = info.getTotalPrice();
			}
		} else {
			totalPrice = info.getTotalPrice();
		}

		return totalPrice;
	}

	/**
	 * 发送支付消息（或者退款消息）
	 * 
	 * @param info
	 * @return
	 */
	public static DeductionRefundInfo sendDeductionOrRefundMsg(
			DeductionRefundInfo info, Head head) {
		DeductionRefundInfo deductionRefundInfo = null;
		int total = DataConversion.toInt(info.getPaymentFee());
		info.setPaymentFee(String.valueOf(total));
		String sign = null; // 签名字符串
		if ("0".equals(info.getPaymentType())) { // 扣款
			sign = getSignStringOfDeduction(info);
		} else if ("1".equals(info.getPaymentType())) { // 退款
			sign = createSignOfRefund(info);
		}

		String url = assembleUrl(info, sign);
		HttpClient httpClient = new HttpClient();
		try {
			// 供应商返回消息编码方式
			String supplyEncode = "UTF-8";
			log.info("请求ID：" + head.getRequestId() + "发送到支付接口的消息：" + url.trim());
			String xmlStr = httpClient.doGet(url, supplyEncode);
			log.info("请求ID：" + head.getRequestId() + "支付接口响应消息：" + xmlStr);
			// 对返回的xml格式字符串数据进行解析
			deductionRefundInfo = DeductionRefundResParse
					.parseDeductRefundRes(xmlStr);
		} catch (Exception e) {
			log.error("请求ID：" + head.getRequestId() + "请求支付接口时出现异常！", e);
		}
		
		return deductionRefundInfo;
	}

	/**
	 * 获取签名字符串(Md5加密32位小写,扣款)
	 * 
	 * @param info
	 * @return
	 */
	private static String getSignStringOfDeduction(DeductionRefundInfo info) {
		// 用户编号
		String userNo = info.getUserNo();
		String orderNo = info.getOrderNo();
		String paymentFee = info.getPaymentFee();
		String paymentType = info.getPaymentType();
		String businessType = "2"; // 业务类型(1充值,2 游戏)
		String paymentIP = info.getPaymentIP();
		String remark = info.getRemark();
		String orderTime = info.getOrderTime();

		// 密钥
		String key = "";
		DeductionRefundInfo deReInfo = DeductionRefundResParse
				.readConfigurateFile();
		key = deReInfo.getKey();

		StringBuilder strBui = new StringBuilder();
		strBui.append(userNo);
		strBui.append(orderNo);
		strBui.append(paymentFee);
		strBui.append(paymentType);
		strBui.append(businessType);
		if (paymentIP != null && !("".equals(paymentIP))) {
			strBui.append(paymentIP);
		}
		if (remark != null && !("".equals(remark))) {
			strBui.append(remark);
		}
		strBui.append(orderTime);
		strBui.append(key.trim());

		String data = strBui.toString().trim();
		String result = "";
		result = UtilMD5Encryption.createMD5Encryption(data);

		return result;
	}

	/**
	 * 生成签名字符串(订单充值失败退款)
	 * 
	 * @param info
	 * @return
	 */
	private static String createSignOfRefund(DeductionRefundInfo info) {
		// 用户编号
		String userNo = info.getUserNo();
		// 手拉手订单号
		String orderNo = info.getOrderNo();
		// 支付单号
		String tradeNo = info.getTradeNo();
		// 支付费用
		String paymentFee = info.getPaymentFee();
		// 支付类型
		String paymentType = info.getPaymentType();
		// 业务类型
		String businessType = "2"; // 1话费充值,2 游戏
		//
		String paymentIP = info.getPaymentIP();
		String remark = info.getRemark();
		// 支付IP地址
		String orderTime = info.getOrderTime();

		// 密钥
		String key = "";
		DeductionRefundInfo deReInfo = DeductionRefundResParse
				.readConfigurateFile();
		key = deReInfo.getKey();
		if (key != null && !("".equals(key))) {
			key = key.trim();
		}

		StringBuilder strBui = new StringBuilder();
		strBui.append(userNo);
		strBui.append(orderNo);
		strBui.append(tradeNo);
		strBui.append(paymentFee);
		strBui.append(paymentType);
		strBui.append(businessType);
		if (StringUtils.isNotEmpty(paymentIP)) {
			strBui.append(paymentIP);
		}
		if (remark != null && !("".equals(remark))) {
			strBui.append(remark);
		}
		strBui.append(orderTime);
		strBui.append(key);
		String data = strBui.toString().trim();
		String result = "";
		result = UtilMD5Encryption.createMD5Encryption(data);

		return result;
	}

	/**
	 * 拼接Http 访问url字符串
	 * 
	 * @param info
	 * 
	 * @param sign
	 */
	private static String assembleUrl(DeductionRefundInfo info, String sign) {
		StringBuilder strBui = new StringBuilder();
		String address = "";
		DeductionRefundInfo deReInfo = DeductionRefundResParse
				.readConfigurateFile();
		address = deReInfo.getAddress();

		String businessType = "2"; // 业务类型(1充值,2 游戏)
		String paymentType = info.getPaymentType();

		strBui.append(address.trim());
		strBui.append("?");
		strBui.append("UserId=");
		strBui.append(info.getUserNo());
		strBui.append("&");
		strBui.append("OrderNo=");
		strBui.append(info.getOrderNo());
		strBui.append("&");
		if ("1".equals(paymentType)) {
			strBui.append("TradeNo=");
			strBui.append(info.getTradeNo());
			strBui.append("&");
		}
		strBui.append("PaymentFee=");
		strBui.append(info.getPaymentFee());
		strBui.append("&");
		strBui.append("PaymentType=");
		strBui.append(info.getPaymentType());
		strBui.append("&");
		strBui.append("BusinessType=");
		strBui.append(businessType);
		strBui.append("&");
		String paymentIP = info.getPaymentIP();
		if (paymentIP != null && !("".equals(paymentIP))) {
			strBui.append("PaymentIP=");
			strBui.append(info.getPaymentIP());
			strBui.append("&");
		}
		String remark = info.getRemark();
		if (remark != null && !("".equals(remark))) {
			strBui.append("Remark=");
			strBui.append(info.getRemark());
			strBui.append("&");
		}
		strBui.append("OrderTime=");
		strBui.append(info.getOrderTime());
		strBui.append("&");
		strBui.append("Sign=");
		strBui.append(sign);

		String result = "";
		result = strBui.toString().trim();
		return result;
	}

	/**
	 * 退款成功，通知下游用户
	 * 
	 * @param orderId
	 *            手拉手订单号
	 * @param dedInfo
	 */
	public static void noticeUserRefundMsg(String orderId,
			DeductionRefundInfo dedInfo, GoodsOrderDAO goodsOrderDAO,
			DownstreamUserDAO downstreamUserDAO,
			GoodsOrderLogDAO goodsOrderLogDAO) {
		GoodsOrderInfo orderInfo = null;
		// 下游用户编号
		String contractId = null;
		// 下游用户订单号
		String merchantOrderId = null;
		orderInfo = goodsOrderDAO.queryByOrderId(orderId);
		if (orderInfo != null) {
			merchantOrderId = orderInfo.getMerchantOrderId();
		}
		contractId = dedInfo.getUserNo();

		DownstreamUserInfo userInfo = null;
		// 退款通知地址
		String refundUrl = null;
		String scretKey = null;
		userInfo = downstreamUserDAO.queryUserByUserNO(contractId);
		if (userInfo != null) {
			refundUrl = userInfo.getRefundUrl();
			scretKey = userInfo.getSecretKey();
		}

		// 退款金额
		String rePrice = dedInfo.getPaymentFee();
		HttpClient httpClient = new HttpClient();
		String url = obtainRefundUrl(contractId, merchantOrderId,
				merchantOrderId, rePrice, refundUrl, scretKey);
		String supplyEncode = "UTF-8";
		if(StringUtils.isNotBlank(url)){
			try {
				String xmlStr = httpClient.doGet(url, supplyEncode);
				if (xmlStr != null && !("".equals(xmlStr))) {
					SLSHttpInterfaceInfo slsInfo = null;
					slsInfo = OrderStatusSendParse.readUserSendMsg(xmlStr);
					if (slsInfo != null) {
						// ...
					}
				}
			} catch (Exception e) {
				log.error("退款通知下游异常",e);
			}
		}
	}

	/**
	 * 退款通知url
	 * 
	 * @param contractId
	 * @param merchantOrderId
	 * @param orderId
	 * @param rePrice
	 * @param refundUrl
	 * @param scretKey
	 * @return
	 */
	private static String obtainRefundUrl(String contractId,
			String merchantOrderId, String orderId, String rePrice,
			String refundUrl, String scretKey) {
		StringBuilder strBui = new StringBuilder();
		if (refundUrl != null && !("".equals(refundUrl))) {
			refundUrl = refundUrl.trim();
			strBui.append(refundUrl);
			strBui.append("?");
			strBui.append("userNo=");
			strBui.append(contractId);
			strBui.append("&");
			strBui.append("ptOrderNo=");
			strBui.append(merchantOrderId);
			strBui.append("&");
			strBui.append("supOrderNo=");
			strBui.append(orderId);
			strBui.append("&");

			strBui.append("reType=");
			strBui.append("1"); // 1：整个订单金额退款 2：订单部分金额退款
			strBui.append("&");
			strBui.append("rePrice=");
			strBui.append(rePrice);
			strBui.append("&");
			strBui.append("sign=");

			String reTypeStr = "1";
			String sign = createSignOfUserRefundMsg(contractId,
					merchantOrderId, orderId, rePrice, reTypeStr, scretKey);
			strBui.append(sign); // 1：整个订单金额退款 2：订单部分金额退款
		}
		String url = strBui.toString().trim();

		return url;
	}

	/**
	 * 创建签名字符串
	 * 
	 * @param contractId
	 * @param merchantOrderId
	 * @param orderId
	 * @param rePrice
	 * @param reType
	 * @param scretKey
	 * @return
	 */
	private static String createSignOfUserRefundMsg(String contractId,
			String merchantOrderId, String orderId, String rePrice,
			String reType, String scretKey) {
		StringBuilder strBui = new StringBuilder();
		strBui.append(contractId); // 合作方用户编号
		strBui.append(merchantOrderId); // 合作方订单编号
		strBui.append(orderId); // 手拉手订单编号
		strBui.append(reType); // 手拉手平台退款种类
		strBui.append(rePrice); // 退款金额
		strBui.append(scretKey); // 密钥

		String data = strBui.toString().trim();
		data = UtilMD5Encryption.createMD5Encryption(data);
		return data;
	}

	/**
	 * 异步回调订单充值结果失败时，退款给下游用户
	 * 
	 * @param orderId
	 * @param goodsOrderDAO
	 * @return
	 * @date 2013-01-04
	 */
	public static DeductionRefundInfo refundWhenAsynCallBackFailed(
			String orderId, GoodsOrderDAO goodsOrderDAO, Head head) {
		GoodsOrderInfo goodsOrderInfo1 = null;
		// 用户编号
		String contractId = null;
		// 订单金额
		String totalPrice = null;
		// 支付类型
		String paymentType = "1"; // 支付类型(0 扣款,1 退款)
		// 下游用户IP地址
		String merchantIP = null;
		// 订单 支付时间
		String orderTime = ServerDateAndTime.getNowDateTime();
		// 支付单号
		String paymentOrderNo = null;
		// 根据手拉手订单号，查询该订单记录
		goodsOrderInfo1 = goodsOrderDAO.queryByOrderId(orderId);
		if (goodsOrderInfo1 != null) {
			contractId = goodsOrderInfo1.getContractId();

			totalPrice = goodsOrderInfo1.getTotalPrice() + "";
			totalPrice = DataConversion.converIntegerToString(totalPrice);

			merchantIP = goodsOrderInfo1.getMerchantIP();
			paymentOrderNo = goodsOrderInfo1.getPaymentOrderNo();
		}

		DeductionRefundInfo deductionRefundInfo = new DeductionRefundInfo();
		deductionRefundInfo.setUserNo(contractId);
		deductionRefundInfo.setOrderNo(orderId);
		deductionRefundInfo.setPaymentFee(totalPrice);
		deductionRefundInfo.setPaymentType(paymentType);
		deductionRefundInfo.setPaymentIP(merchantIP);
		deductionRefundInfo.setOrderTime(orderTime);
		deductionRefundInfo.setTradeNo(paymentOrderNo);

		DeductionRefundInfo deReFunInfo = null;
		deReFunInfo = sendDeductionOrRefundMsg(deductionRefundInfo, head);

		return deReFunInfo;
	}

}
